package simulator;

/**
 * This is the class that simulates the entire system. Different components communicate and change each other's state through
 * the system simulator.
 * There is only one system simulator, so we make a static reference to it
 * @author Paul
 *
 */
public class SystemSim {
	
	private int currentTime;
	int aCommit; //asynchromis commit time interval
	int aCheckpoint; //asynchronous checkpoint time interval
	Policy policy;
	FileSystem fs;
	JournalArea ja;
	BufferCache bc;
	
	public SystemSim(int comm, int check){
		currentTime = 0;
		aCommit = comm;
		aCheckpoint = check;
	}
	
	public SystemSim(int comm, int check, Policy p, FileSystem fs, JournalArea ja, BufferCache bc){
		currentTime = 0;
		aCommit = comm;
		aCheckpoint = check;
		this.policy = p;
		this.fs = fs;
		this.ja = ja;
		this.bc = bc;

	}
	
	/*
	public void updateFile(String fileName, int newData)
	{
	fileSystem.updateFile(fileName, newData);	
	}*/
	
	public int getTime()
	{return currentTime;}
	
	public void UpdateTime()
	{
		currentTime++;
		
		switch(policy.getPolicy())
		{
		case Policy.Sync:
			sycnUpdateTime();
			break;
			
		case Policy.Async:
			asyncUpdateTime();
			break;
			
		case Policy.UBJ:
			UBJUpdateTime();
			break;
			
			default:
				System.out.print("Wrong kind of policy!");
				break;
		}
	}
	
	public void sycnUpdateTime()
	{
		if(currentTime % aCheckpoint == 0) //Time for a checkpoint
		{
			ja.Checkpoint(); //trigger checkpoint from journal area to disk
		}
	}
	
	public void asyncUpdateTime()
	{
		// Time for commit for async system.
		if(currentTime % aCommit == 0)
		{
			bc.commitAll();
		}
		
		// Time for a checkpoint for async systme, same as sync one
		if(currentTime % aCheckpoint == 0)
		{
			ja.checkpointAll();
		}
		
	}
	
	public void UBJUpdateTime()
	{
		// Time for commit for async system.
		if(currentTime % aCommit == 0)
		{
			bc.commitAll();
		}
		
		// Time for a checkpoint for async systme, same as sync one
		if(currentTime % aCheckpoint == 0)
		{
			bc.checkpointAll();
			((UBJCache)bc).UpdateCheckPtTimer();
		}
	}
	
	public String simString(){
	String str;
	int totalWrites = fs.getWrites() + ja.getWrites();
	str = bc.SimString() + "\n" + ja.simString() + "\n" + fs.SimString()
			+ "\nNumber of total writes: " + totalWrites;
	return str;
	}
}
